#include "JKProcessMonitor.h"
#include <QDebug>
#include <QFileInfo>
#include <QTimer>
#include <QThread>
#include <QMutexLocker>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QTextCodec>
#include "JKCommunicationInterProcess.h"
#include "WinAPI.h"

#define TIME_INTERVAL 7200000
//#define TIME_INTERVAL 60000

#define HOST_NAME  "192.168.2.72"
const char *DOOR = "/service/door/";
const char *DINGTALK = "/service/dingtalk/";
const quint16 LISTEN_PORT = 8999;

JKProcessMonitor::JKProcessMonitor(QObject *parent) : QObject(parent)
{
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));
    setTimer(TIME_INTERVAL);

    bool bRet = mServer.listen(LISTEN_PORT);
    qDebug() << QStringLiteral("开启 Http服务 %1，侦听端口:%2").arg(bRet ? "OK" : "Failed").arg(LISTEN_PORT);
    bRet = connect(&mServer, &QHttpServer::newRequest, this, &JKProcessMonitor::procRequest);
    if (!bRet) {
        qDebug() << QStringLiteral("QHttpServer::newRequest信号连接槽失败！");
    }
    else {
        qDebug() << QStringLiteral("QHttpServer::newRequest信号连接槽成功！");
    }

    JKCommunicationInterProcess *pIn = new JKCommunicationInterProcess(this);
    connect(this, &JKProcessMonitor::publish, pIn, &JKCommunicationInterProcess::publish);
    pIn->startListen();

}

JKProcessMonitor::~JKProcessMonitor()
{
    mServer.close();
}

bool JKProcessMonitor::execute(const QString &program, const QStringList &arguments, QByteArray &result, QProcess::ProcessChannelMode channelMode)
{
    qDebug() << QString("Execute Command: %1 %2").arg(program, arguments.join(' '));
    QProcess process;
    QString strPath = QFileInfo(program).absolutePath();
    process.setWorkingDirectory(strPath);
    process.setProgram(program);
    process.setArguments(arguments);
    process.setProcessChannelMode(channelMode);
    process.start(QIODevice::ReadOnly);
    process.waitForFinished(-1);
    if (channelMode != QProcess::MergedChannels) {
        if (channelMode == QProcess::ForwardedOutputChannel)
            process.setReadChannel(QProcess::StandardOutput);
        else
            process.setReadChannel(QProcess::StandardError);
    }
    result = process.readAllStandardOutput();

    return true;
}

void JKProcessMonitor::start()
{
    mMutex.lock();
    if (mTimerState != START) { // Timer未启动
        mMutex.unlock();
        setTimer(TIME_INTERVAL);
    }
    else {  // Timer已启动，等待Timer事件触发，忽略本次启动
        mMutex.unlock();
    }

    mNeedStop = false;
}

void JKProcessMonitor::stop()
{
    mNeedStop = true;
}

void JKProcessMonitor::setTimer(int msec)
{
    QMutexLocker locker(&mMutex);
    QTimer::singleShot(msec, this, SLOT(timeout()));
    mTimerState = START;
}

void JKProcessMonitor::timeout()
{
    if (mNeedStop) {
        QMutexLocker locker(&mMutex);
        mTimerState = STOP;
        return;
    }

    QString mAdbCommand("D:/Android/Sdk/platform-tools/adb.exe");
    QStringList arguments = QStringList() << "devices";
    QByteArray baOutput;
    execute(mAdbCommand, arguments, baOutput);
    QStringList lstDevice = QString(baOutput).split("\r\n");
    QRegularExpression reg("^(?<sn>\\S+)\\s+(?<status>\\w+)$");
    bool hasConnected = false;
    bool isUnauthorized = false;
    foreach(QString line, lstDevice) {
        QRegularExpressionMatch matchResult = reg.match(line);
        if (matchResult.hasMatch()) {
            QString strSN = matchResult.captured("sn");
            QString strStatus = matchResult.captured("status");
            qDebug() << QStringLiteral("已连接设备. 序列号: %1       %2").arg(strSN,strStatus);
            if (strSN.contains(HOST_NAME, Qt::CaseInsensitive))
            {
                if (strStatus.compare("device", Qt::CaseInsensitive) == 0)
                    hasConnected = true;
                else
                    isUnauthorized = true;

                break;
            }
        }
    }

    arguments.clear();
    if (hasConnected) {
        arguments = QStringList() << "disconnect" << "192.168.2.72";
        execute(mAdbCommand, arguments, baOutput);
    }
    else if (isUnauthorized) {
        arguments = QStringList() << "kill-server";
        execute(mAdbCommand, arguments, baOutput);
        QThread::sleep(3);
        arguments = QStringList() << "connect" << "192.168.2.72";
        execute(mAdbCommand, arguments, baOutput);
    }
    else {
        arguments = QStringList() << "connect" << "192.168.2.72";
        execute(mAdbCommand, arguments, baOutput);
    }
    setTimer(TIME_INTERVAL);
}

void JKProcessMonitor::procRequest(QHttpRequest *request, QHttpResponse *resp)
{
    qDebug() << QStringLiteral("网络请求.")
             << QStringLiteral("Method类型:") << request->method()
             << "URL:" << request->url()
             << "Path:" << request->path()
             << QStringLiteral("远程主机(%1/%2)").arg(request->remoteAddress()).arg(request->remotePort());
//    QMap<QString, QString> postData;
//    postData.insert("pass", "ym123456");
//    QWebEngineHttpRequest::postRequest(QUrl("http://192.168.2.99:8090/device/openDoorControl"), postData);


    QString strPath = request->path();
    if (strPath.startsWith(DOOR, Qt::CaseInsensitive))
    {
        QStringList arguments;
        int doorNo;
        char *pszURL = new char[strlen(DOOR) + strlen("%d") + 1];
        sprintf(pszURL, "%s%%d", DOOR);
        sscanf_s(strPath.toLatin1(), pszURL, &doorNo);
        delete [] pszURL;
        QString strDeviceIP;
        QString mCommand("curl.exe");
        QByteArray baOutput;
        if (doorNo==1)
            arguments = QStringList() << "-d" << "pass=ym123456" << "http://192.168.2.99:8090/device/openDoorControl";
        else if (doorNo==2)
            arguments = QStringList() << "-d" << "pass=ym123456" << "http://192.168.2.101:8090/device/openDoorControl";
        else {
            baOutput = QStringLiteral("门号错误. 可选的门号是[1,2].").toUtf8();
            qDebug() << baOutput;
        }
        if (arguments.size() > 0) {
            execute(mCommand, arguments, baOutput, QProcess::ForwardedErrorChannel);
            qDebug() << QString(baOutput);
        }

        resp->writeHead(200); // everything is OK
        resp->write(QString(baOutput).toLocal8Bit());
        resp->end();
    }
    if (strPath.startsWith(DINGTALK, Qt::CaseInsensitive))
    {
        if (mTimerState == START)
        {
            mNeedStop = TRUE;
        }
        QRegularExpression reg("/service/dingtalk/(?<type>[a-zA-Z-_]+)/?");
        QRegularExpressionMatch match = reg.match(strPath);

        if (match.hasMatch()) {
            QStringList arguments;
            QString clock_command = match.captured("type");
            qDebug() << QStringLiteral("DingTalk命令：%1").arg(clock_command);

//            emit publish(clock_command);

            std::wstring app = L"cmd.exe";
            std::vector<std::wstring> params;
            params.push_back(L"/c");

            QString mCommand;
            if (clock_command.compare("clock_in", Qt::CaseInsensitive) == 0) {

//                mCommand = "cmd /c D:\\GreenSoftware\\scrcpy\\ding_clock_in.bat";
                params.push_back(L"D:\\GreenSoftware\\scrcpy\\ding_clock_in.bat");
            }
            else if (clock_command.compare("clock_out", Qt::CaseInsensitive) == 0) {
//                mCommand = "cmd /c D:\\GreenSoftware\\scrcpy\\ding_clock_out.bat";
                params.push_back(L"D:\\GreenSoftware\\scrcpy\\ding_clock_out.bat");
            }
            else {
                qDebug() << QStringLiteral("Clocking-in命令错误. 可选的命令是[clock_in,clock_out].");
                return;
            }

            if (launchGUIApplication(app, params) == FALSE) {
                qDebug() << QStringLiteral("启动程序[%1]失败.").arg(app);
            }
//            QByteArray baOutput;
//            execute(mCommand, arguments, baOutput);

            this->start();
        }
        resp->writeHead(200); // everything is OK
        resp->write("Welcome!");
        resp->end();
    }
    else {
        resp->writeHead(200); // everything is OK
        resp->write("Welcome to access!");
        resp->end();
    }
}
